package com.talkyun.openx;

import com.talkyun.openx.client.RestfulJsonProxy;

import java.lang.reflect.Proxy;
import java.util.concurrent.ThreadPoolExecutor;

public class RestfulServiceFactory {
    private String url;
    private int timeout = 3 * 1000; // 3 second

    private String httpProxyAddress;       // host:port
    private String httpProxyAuthorization; // username:password

    public RestfulServiceFactory() {
    }

    @Deprecated
    public RestfulServiceFactory(boolean sync) {
        // Deprecated
    }

    public RestfulServiceFactory(String url) {
        this(url, 2);
    }

    @Deprecated
    public RestfulServiceFactory(String url, int threadNum) {
        this.url = url;
    }

    @Deprecated
    public RestfulServiceFactory(String url, ThreadPoolExecutor executor) {
        this.url = url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setTimeout(int timeout) {
        if (timeout < 500) {
            throw new RuntimeException("Timeout setting is too small! " + timeout);
        }
        this.timeout = timeout;
    }

    public void setHttpProxyAddress(String httpProxyAddress) {
        this.httpProxyAddress = httpProxyAddress;
    }

    public void setHttpProxyAuthorization(String httpProxyAuthorization) {
        this.httpProxyAuthorization = httpProxyAuthorization;
    }

    @Deprecated
    public void setSyncInvoke(boolean sync) {
    }

    @Deprecated
    public void setExecutor(ThreadPoolExecutor executor) {
    }

    public String getUrl() {
        return url;
    }

    public <T> T getService(String mapping, Class<T> clazz) {
        return this.getService(mapping, clazz, timeout);
    }

    @SuppressWarnings("unchecked")
    public <T> T getService(String mapping, Class<T> clazz, int timeout) {
        try {
            return (T) getRemoteProxy(mapping, clazz, timeout);
        } catch (Exception e) {
            throw new RuntimeException("Can't lookup " + mapping + ":" + clazz.getName(), e);
        }
    }

    public <T> T getService(Class<T> clazz) {
        return getService(null, clazz);
    }

    public <T> T getService(Class<T> clazz, int timeout) {
        return getService(null, clazz, timeout);
    }

    protected boolean isBlank(String s) {
        return s == null || s.trim().length() == 0;
    }

    private Object getRemoteProxy(String mapping, Class<?> clazz, int timeout) {
        if (mapping == null) {
            mapping = this.getServiceMapping(clazz);
        }

        RestfulJsonProxy proxy = new RestfulJsonProxy(url, mapping.toLowerCase(), timeout);
        proxy.setApiClass(clazz);
        if (!isBlank(httpProxyAddress)) {
            proxy.setHttpProxyAddress(httpProxyAddress);
        }
        if (!isBlank(httpProxyAuthorization)) {
            proxy.setHttpProxyAuthorization(httpProxyAuthorization);
        }

        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        return Proxy.newProxyInstance(loader, new Class[]{clazz}, proxy);
    }

    private String getServiceMapping(Class<?> clazz) {
        // ex: com.talkyun.game.UserService => game/UserService
        String[] parts = clazz.getName().split("\\.");
        if (parts.length > 1) {
            return parts[parts.length - 2] + "/" + parts[parts.length - 1];
        } else {
            return clazz.getName();
        }
    }

}